package com.sys.server.common.aspect;

import com.alibaba.fastjson.JSON;
import com.sys.server.common.annotation.Log;
import com.sys.server.common.utils.HttpServletUtil;
import com.sys.server.common.utils.TimeFormatUtil;
import com.sys.server.modules.entity.OperLogEntity;
import com.sys.server.modules.mapper.OperLogMapper;
import com.sys.server.modules.service.TokenService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.time.Instant;
import java.util.Date;

@Aspect
@Component
public class LogAspect {

    private static final Logger LOG = LoggerFactory.getLogger(LogAspect.class);

    @Resource
    private OperLogMapper logMapper;

    @Autowired
    private TokenService tokenService;

    @Pointcut(value = "@annotation(com.sys.server.common.annotation.Log)")
    public void pointcut() {
    }

    /**
     * 环绕通知，用于记录用户操作
     *
     * @param proceedingJoinPoint 用户操作
     * @throws Throwable 异常
     */
    @Around(value = "pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Date beginTime = new Date();
        Object result = null;
        try {
            result = proceedingJoinPoint.proceed();
        } catch (Exception e) {
            LOG.error("用户操作执行失败！" + e.getMessage());
        }

        try {
            saveSysLog(proceedingJoinPoint, beginTime);
        } catch (Exception e) {
            LOG.error("系统日志保存出错{}" + e.getMessage());
        }
        return result;
    }

    private void saveSysLog(ProceedingJoinPoint proceedingJoinPoint, Date time) {
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();

        OperLogEntity sysLog = new OperLogEntity();
        sysLog.setTime(time);

        Log log = method.getAnnotation(Log.class);
        if (log != null) {
            sysLog.setOperation(log.module() + " - " + log.action());
            sysLog.setType(log.type());
        }

        String className = proceedingJoinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");

        try {
            Object[] args = proceedingJoinPoint.getArgs();
            String params = "";
            if (args.length != 0) {
                params = JSON.toJSONString(args);
            }
            LOG.info("参数长度:" + params.length());
            sysLog.setParams(params);
        } catch (Exception e) {
            LOG.error("获取请求参数失败：{}" + e.getMessage());
        }
        sysLog.setIp(HttpServletUtil.getClientIpAddr());
        sysLog.setUid(tokenService.getCurrentUser());

        try {
            int row = logMapper.insert(sysLog);
            if (row == 0) {
                LOG.error("记录用户操作失败");
            }
        } catch (Exception e) {
            LOG.error("记录用户操作遇到错误:{" + e.getMessage() + "}");
        }
    }

}
